package com.lord.rowcopy.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lord.rowcopy.common.constant.AbstractKonstants;

public abstract class DataHelper {

    private static final Logger log = LoggerFactory.getLogger(DataHelper.class);

    public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }

    public static boolean isNotEmpty(String str) {
        return str != null && str.length() > 0;
    }

    public static boolean isEmpty(Object[] objects) {
        return objects == null || objects.length == 0;
    }

    public static boolean isNotEmpty(Object[] objects) {
        return objects != null && objects.length > 0;
    }

    public static <E extends Object> boolean isEmpty(Collection<E> collection) {
        return collection == null || collection.isEmpty();
    }

    public static <E extends Object> boolean isNotEmpty(Collection<E> collection) {
        return collection != null && !collection.isEmpty();
    }

    public static <K extends Object, V extends Object> boolean isEmpty(Map<K, V> mapper) {
        return mapper == null || mapper.isEmpty();
    }

    public static <K extends Object, V extends Object> boolean isNotEmpty(Map<K, V> mapper) {
        return mapper != null && !mapper.isEmpty();
    }

    public static boolean contains(String symbols, String symbol) {
        return symbols != null && symbol != null && (',' + symbols + ',').contains(',' + symbol + ',');
    }

    public static boolean contains(String symbols, int symbol) {
        return symbols != null && (',' + symbols + ',').contains(',' + Integer.toString(symbol) + ',');
    }

    @SuppressWarnings("unchecked")
    public static <T> List<T> deepCopy(List<T> srcList) throws Exception {
        List<T> destList = null;

        ByteArrayOutputStream byteOut = null;
        ObjectOutputStream out = null;

        ByteArrayInputStream byteIn = null;
        ObjectInputStream in = null;

        try {
            byteOut = new ByteArrayOutputStream();
            out = new ObjectOutputStream(byteOut);
            out.writeObject(srcList);

            byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            in = new ObjectInputStream(byteIn);
            destList = (List<T>) in.readObject();
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (in != null) {
                    in.close();
                }

                if (byteIn != null) {
                    byteIn.close();
                }

                if (out != null) {
                    out.close();
                }

                if (byteOut != null) {
                    byteOut.close();
                }
            } catch (Exception e) {
                throw e;
            }
        }

        return destList;
    }

    public static List<Integer> getIntList(String string) {
        return getIntList(string, Character.toString(','));
    }

    public static List<Integer> getIntList(String string, String seperator) {
        if (isEmpty(string) || isEmpty(seperator)) {
            return null;
        }

        List<Integer> intList = new ArrayList<>();

        for (String str : string.split(seperator)) {
            intList.add(Integer.parseInt(str));
        }

        return intList;
    }

    public static List<String> getStrList(String string) {
        return getStrList(string, Character.toString(','));
    }

    public static List<String> getStrList(String string, String seperator) {
        return isNotEmpty(string) && isNotEmpty(seperator) ? Arrays.asList(string.split(seperator)) : null;
    }

    public static <E extends Object> String toStr(Collection<E> collection) {
        return toStr(collection, Character.toString(','));
    }

    public static <E extends Object> String toStr(Collection<E> collection, String seperator) {
        return isNotEmpty(collection) && isNotEmpty(seperator) ? StringUtils.join(collection, seperator) : null;
    }

    public static String trim(String str) {
        return str != null ? str.trim() : null;
    }

    public static String clip(String str) {
        return str != null ? str.trim() : StringUtils.EMPTY;
    }

    public static Integer toInteger(String data) {
        try {
            return Integer.parseInt(data);
        } catch (Exception e) {
            return null;
        }
    }

    public static Double toDouble(String data) {
        try {
            return Double.parseDouble(data);
        } catch (Exception e) {
            return null;
        }
    }

    public static byte[] objectToBytes(Object obj) {
        byte[] bytes = null;

        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;

        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(obj);
            objectOutputStream.flush();
            bytes = byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            try {
                if (objectOutputStream != null) {
                    objectOutputStream.close();
                }

                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (Exception e) {
                log.error(e.toString());
            }
        }

        return bytes;
    }

    public static Object bytesToObject(byte[] bytes) {
        Object obj = null;

        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;

        try {
            byteArrayInputStream = new ByteArrayInputStream(bytes);
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            obj = objectInputStream.readObject();
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            try {
                if (objectInputStream != null) {
                    objectInputStream.close();
                }

                if (byteArrayInputStream != null) {
                    byteArrayInputStream.close();
                }
            } catch (Exception e) {
                log.error(e.toString());
            }
        }

        return obj;
    }

    public static String readFromTextFile(String fileName) {
        return readFromTextFile(new File(fileName));
    }

    public static String readFromTextFile(File file) {
        BufferedReader reader = null;

        try {
            StringBuilder text = new StringBuilder();
            String line = null;

            reader = new BufferedReader(new FileReader(file));

            while ((line = reader.readLine()) != null) {
                text.append(AbstractKonstants.LINE_SEPARATOR);
                text.append(line.trim());
            }

            if (text.length() > 0) {
                return text.substring(AbstractKonstants.LINE_SEPARATOR.length());
            }
        } catch (Exception e) {
            log.error("read from text file error: {}", e.toString());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                log.error(e.toString());
            }
        }

        return null;
    }

    public static void writeToTextFile(String fileName, String text) {
        writeToTextFile(fileName, text, false);
    }

    public static void writeToTextFile(String fileName, String text, boolean append) {
        writeToTextFile(new File(fileName), text, append);
    }

    public static void writeToTextFile(File file, String text) {
        writeToTextFile(file, text, false);
    }

    public static void writeToTextFile(File file, String text, boolean append) {
        BufferedWriter writer = null;

        try {
            writer = new BufferedWriter(new FileWriter(file, append));
            writer.write(text);
        } catch (Exception e) {
            log.error("write to text file error: {}", e.toString());
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (Exception e) {
                log.error(e.toString());
            }
        }
    }

    public static void printInvokeTrace() {
        if (log.isDebugEnabled()) {
            StringBuilder builder = new StringBuilder();
            Exception e = new Exception("查看方法调用栈");
            StackTraceElement[] trace = e.getStackTrace();
            String methodName = null;

            for (int i = 1; i < trace.length; i++) {
                if (trace[i].toString().indexOf("com.alg") == 0) {
                    if (i == 1) {
                        methodName = trace[i].getClassName().substring(trace[i].getClassName().lastIndexOf('.') + 1)
                                + '.' + trace[i].getMethodName();
                    }

                    builder.append(AbstractKonstants.LINE_SEPARATOR).append("\t[").append(i - 1).append("] ")
                            .append(trace[i]);
                }
            }

            log.debug("方法[{}]调用栈: {}", methodName, builder.toString());
        }
    }

}
